/*
 * Created by SharpDevelop.
 * User: MyWife
 * Date: 7/11/2010
 * Time: 12:37 AM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using popLib;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.IO;
using popLib.ExtensionClass;

namespace WebRemoteDesktop
{
	/// <summary>
	/// Description of MainForm.
	/// </summary>
	public partial class MainForm : Form
	{
		string server, url_upload, url_cmd;
		string file_cmd   = FileLib.getFullPath("command.txt");
		INISetting config;
		
		Timer timer, temp;
		bool showForm = false;
		public enum VK : int
		{
			SHIFT        = 0x10,
			CONTROL      = 0x11,
			CTRL         = 0x11,
			ALT			 = 0x12,
			MENU         = 0x12,
			ESCAPE       = 0x1B,
			BACK         = 0x08,
			BACKSPC      = 0x08,
			TAB          = 0x09,
			RETURN       = 0x0D,
			ENTER        = 0x0D,
			PRIOR        = 0x21,
			NEXT         = 0x22,
			END          = 0x23,
			HOME         = 0x24,
			LEFT         = 0x25,
			UP           = 0x26,
			RIGHT        = 0x27,
			DOWN         = 0x28,
			SELECT       = 0x29,
			PRINT        = 0x2A,
			EXECUTE      = 0x2B,
			SNAPSHOT     = 0x2C,
			INSERT       = 0x2D,
			DELETE       = 0x2E,
			DEL          = 0x2E,
			HELP         = 0x2F,
			NUMPAD0      = 0x60,
			NUMPAD1      = 0x61,
			NUMPAD2      = 0x62,
			NUMPAD3      = 0x63,
			NUMPAD4      = 0x64,
			NUMPAD5      = 0x65,
			NUMPAD6      = 0x66,
			NUMPAD7      = 0x67,
			NUMPAD8      = 0x68,
			NUMPAD9      = 0x69,
			MULTIPLY     = 0x6A,
			ADD          = 0x6B,
			SEPARATOR    = 0x6C,
			SUBTRACT     = 0x6D,
			DECIMAL      = 0x6E,
			DIVIDE       = 0x6F,
			F1           = 0x70,
			F2           = 0x71,
			F3           = 0x72,
			F4           = 0x73,
			F5           = 0x74,
			F6           = 0x75,
			F7           = 0x76,
			F8           = 0x77,
			F9           = 0x78,
			F10          = 0x79,
			F11          = 0x7A,
			F12          = 0x7B,
			OEM_1        = 0xBA,   // ',:' for US
			OEM_PLUS     = 0xBB,   // '+' any country
			OEM_COMMA    = 0xBC,   // ',' any country
			OEM_MINUS    = 0xBD,   // '-' any country
			OEM_PERIOD   = 0xBE,   // '.' any country
			OEM_2        = 0xBF,   // '/?' for US
			OEM_3        = 0xC0,   // '`~' for US
			MEDIA_NEXT_TRACK     = 0xB0,
			MEDIA_PREV_TRACK     = 0xB1,
			MEDIA_STOP           = 0xB2,
			MEDIA_PLAY_PAUSE     = 0xB3,
			LWIN       =0x5B,
			WIN        =0x5B,
			RWIN       =0x5C
		}
		string log_file = FileLib.getFullPath( string.Format( "Log_{0}.txt", DateTime.Now.ToString("yyyyMMdd") ) );
		int tempcounter = 5;
		
		public MainForm()
		{
			//
			// The InitializeComponent() call is required for Windows Forms designer support.
			//
			InitializeComponent();
			
			//init();
			
//			Common a = new Common();
//			a.CaptureScreen();
//			this.Opacity = 0;
			
		}
		
		
		
		void init(){
			try{
				config = new INISetting("WebRemoteDesktop.ini");
				
				nud_delay.Value = NumberLib.getInt( config.GetValue("Setting", "Delay", "1000") );
				string serverlist = config.GetValue("Setting", "Server", "http://web");
				string[] servers = StringLib.splitByAny( serverlist, ",;|" );
				foreach( string server in servers ){
					if( StringLib.isValid( server ) && lbx_server.FindStringExact(server) == -1 )
						lbx_server.Items.Add( server );
				}
				
				string currentServer = config.GetValue("Setting", "CurrentServer", "http://web");
				lbx_server.SelectedIndex = lbx_server.FindStringExact(currentServer) == -1 ? 0 : lbx_server.FindStringExact(currentServer);
				
				cbx_httpRequest.Checked = config.GetValue("Setting", "HTTP", "0") == "1";
				
				timer  = new Timer();				
				timer.Tick += delegate { 
					getCommand();
					this.Visible = showForm;
				};
				
				
				temp = new Timer();				
				temp.Interval = 1000;
				temp.Tick+= delegate { 
					
					if( tempcounter == -2 ){
						log.Text = "";
						temp.Stop();
						return;
					}
					
					if( tempcounter == -3 ){
						log.Text = "Auto start is disabled...";	
						tempcounter = -2;
						return;
					}
					
					
					log.Text = "Auto start in "+tempcounter+" seconds.\r\nClick here to cancel.";
					tempcounter--;
					
					if( tempcounter == 0 ){
						log.Text = "Starting...";
						btn_start.PerformClick();
						temp.Stop();
					}
					
					
				};
				temp.Start();
				
			}catch(Exception ex){ FileLib.WriteLog( log_file, ex, "init" ); }
		}
		
		void getCommand(){
			try{
				log.Text = "";
				
				timer.Stop();
				ReturnSet rs;
				
				if( cbx_httpRequest.Checked )
					rs = NetLib.downloadFileHttp(url_cmd, file_cmd, null, null);
				else rs = NetLib.DownloadFile(url_cmd, file_cmd, null);
				
				if( !rs.Success || !File.Exists(file_cmd) ){
					timer.Start();
					log.AppendText("cannot download command\r\n\r\n"+rs.Result);
					return;
				}			
				
				string command = FileLib.readFile(file_cmd);
				if( command == "NO_COMMAND" || !command.StartsWith("COMMAND") ){
					timer.Start();
					log.AppendText("no command\r\n\r\n");
					return;
				}
				
				parseCommand( command );		
						
				timer.Start();
			}catch(Exception ex){ FileLib.WriteLog( log_file, ex, "getCommand" ); }
		}
		
		
		
		void parseCommand( string command ){
			try{
				int x, y;
				string[] commands = StringLib.splitByAny( command, new string[]{"\r\n"} );
				switch( commands[1] ){
					case "CLICK":
						x = NumberLib.getInt( commands[2] );
						y = NumberLib.getInt( commands[3] );
						executeMouseClick( MouseButtons.Left, x, y );
						System.Threading.Thread.Sleep(1000);
						executeUploadScreen();
						break;
						
					case "DOUBLE_CLICK":
						x = NumberLib.getInt( commands[2] );
						y = NumberLib.getInt( commands[3] );
						executeMouseClick( MouseButtons.Left, x, y );
						executeMouseClick( MouseButtons.Left, x, y );
						System.Threading.Thread.Sleep(1000);
						executeUploadScreen();
						break;
						
					case "RIGHT_CLICK":
						x = NumberLib.getInt( commands[2] );
						y = NumberLib.getInt( commands[3] );
						executeMouseClick( MouseButtons.Right, x, y );			
						System.Threading.Thread.Sleep(1000);
						executeUploadScreen();
						break;
						
					case "TYPE":
						
						x = NumberLib.getInt( commands[2] );
						y = NumberLib.getInt( commands[3] );
						executeMouseClick( MouseButtons.Left, x, y );
						
						string content = commands[4];					
						executePaste( content );					
						
						System.Threading.Thread.Sleep(1000);
						executeUploadScreen();					
						break;
						
					case "CAPTURE":
						executeUploadScreen();
						break;				
				}
			}catch(Exception ex){ FileLib.WriteLog( log_file, ex, "parseCommand" ); }
		}
		
		string file_last = "screen_last.jpg";
		void executeUploadScreen(){
			try{
				lock(file_last){
					int counter = 0;
					bool result = false;
					string file = "screen.jpg";				
					while(!result){
						try{
							if( File.Exists(file) ) File.Delete(file);
							ImageBitmap.Save(file, ImageFormat.Gif);
							//File.Copy( file, file_last );
							result = true;
						}catch{
							counter++;
							file = "screen"+counter+".jpg";
						}
					}
					
					log.AppendText("begin upload image\r\n");
					ReturnSet rs1 = new ReturnSet();
					//if( cbx_httpRequest.Checked )
						//rs1  = NetLib.uploadFileHttp( file, url_upload, null, "file", null );
					//else rs1 = NetLib.uploadFile( url_upload, file );
					
					if( !rs1.Success ){
						log.AppendText("upload fail: "+rs1.Result+" \r\n");
						timer.Start();
						return;
					}
					log.AppendText("upload done.\r\n\r\n");	
				}
			}catch(Exception ex){ FileLib.WriteLog( log_file, ex, "executeUploadScreen" ); }
		}
		
		
		[DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
		public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
		
		private const int MOUSEEVENTF_LEFTDOWN = 0x02;
		private const int MOUSEEVENTF_LEFTUP = 0x04;
		private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
		private const int MOUSEEVENTF_RIGHTUP = 0x10;

		
		void executeMouseClick( MouseButtons mouseButton, int x, int y){
			try{
				Cursor.Position = new Point(x, y);
				if( mouseButton == MouseButtons.Left )
					mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, x, y, 0, 0);
				else if( mouseButton == MouseButtons.Right )
					mouse_event(MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP, x, y, 0, 0);			
				log.AppendText("mouse "+ (mouseButton == MouseButtons.Left ? "left":"right") +" click at "+x+", "+y+".\r\n");
			}catch(Exception ex){ FileLib.WriteLog( log_file, ex, "executeMouseClick" ); }
		}
		
				
		
		[DllImport("user32.dll")]
    	private static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);    	    	
		
		const int KEYEVENTF_EXTENDEDKEY = 0x01;
		const int KEYEVENTF_KEYUP       = 0x02;
		
		void executePaste(string content){
			try{
				string[] lines = content.Split('\n');
				
				foreach( string line in lines ){
	    			try{
	    				string[] keys = line.Replace("\r","").Split('+');
						
	    				foreach( string key in keys ){
							if( key.Length != 1 ){
	    						VK vkey = (VK)Enum.Parse( typeof(VK), key.ToUpper() );
								keybd_event ( (byte)vkey , 0, 0, 0);
							}else{
								keybd_event ( Convert.ToByte( Convert.ToInt16( key.ToUpper()[0] ) ) , 0, 0, 0);
							}
						}
						
						foreach( string key in keys ){
							if( key.Length != 1 ){
	    						VK vkey = (VK)Enum.Parse( typeof(VK), key.ToUpper() );
								keybd_event ( (byte)vkey , 0, KEYEVENTF_KEYUP, 0);
								keybd_event ( (byte)vkey , 0, KEYEVENTF_KEYUP, 0);
							}else{
								keybd_event ( Convert.ToByte( Convert.ToInt16(key.ToUpper()[0]) ) , 0, KEYEVENTF_KEYUP , 0);
							}
						}    			
	    			}catch{
						doPaste(line);
					}
				}
			}catch(Exception ex){ FileLib.WriteLog( log_file, ex, "executePaste" ); }
		}
		
		void doPaste(string content){
			try{
				if( content == null || content.Length == 0 ) return;
				
				//copy to clipboard
				Clipboard.SetText( content );
				
				//Ctrl + V
				keybd_event ( (byte)VK.CONTROL , 0, 0, 0);
				keybd_event ( Convert.ToByte( Convert.ToInt16('V') ) , 0, 0, 0);
				
				keybd_event ( (byte)VK.CONTROL, 0, 2, 0);
				keybd_event ( Convert.ToByte( Convert.ToInt16('V') ), 0, 2, 0);
			}catch(Exception ex){ FileLib.WriteLog( log_file, ex, "doPaste" ); }
		}
    		
		
		public Bitmap ImageBitmap
		{
			get
			{
				Rectangle screenShot;
				Bitmap sBit;
				
				//Drawing a Rectangle
				screenShot = System.Windows.Forms.Screen.PrimaryScreen.Bounds;
				
				//Set image size and format
				sBit = new Bitmap(screenShot.Width, screenShot.Height, PixelFormat.Format32bppArgb);
				Graphics sGraphic = Graphics.FromImage(sBit);
				
				//Capture From Screen
				sGraphic.CopyFromScreen(screenShot.Left, screenShot.Top, 0, 0, screenShot.Size);
				
				return sBit;
			}
		}
		
		
		
		void ExitToolStripMenuItemClick(object sender, EventArgs e)
		{
			this.Close();
		}
		
		void NotifyIcon1MouseClick(object sender, MouseEventArgs e)
		{
			if( e.Button == MouseButtons.Left ){
				showForm = !showForm;
				this.Visible = showForm;
			}
			
			if( e.Button == MouseButtons.Middle ){
				this.Close();
			}
		}
		
		void saveConfig(){
			
			string serverlist = "";
			foreach( string item in lbx_server.Items ){
				serverlist += item + ",";
			}
			
			config.SetValue( "Setting", "Server", serverlist );
			config.SetValue( "Setting", "Delay", nud_delay.Value.ToString() );						
			config.SetValue( "Setting", "CurrentServer", lbx_server.SelectedItem.ToString() );
			config.SetValue("Setting", "HTTP", cbx_httpRequest.Checked ? "1" : "0" );
			config.Save();
		}
		
		void Btn_addurlClick(object sender, EventArgs e)
		{
			string url = "http://" + txt_url.Text.Trim().ToLower().Replace("http://","");
			
			if( StringLib.isValid(url) && lbx_server.FindStringExact(url) == -1 ){				
				lbx_server.Items.Add( url );
				saveConfig();
			}			
		}
		
		void Btn_removeurlClick(object sender, EventArgs e)
		{
			if( lbx_server.SelectedIndex >= 0 ){
				lbx_server.Items.RemoveAt( lbx_server.SelectedIndex );
				saveConfig();
			}			
		}
		
		void Btn_startClick(object sender, EventArgs e)
		{
			if( btn_start.Text == "&Start" ){
				
				server     = lbx_server.SelectedItem.ToString();
				url_upload = (server + "/upload.php").Replace("//upload.php","/upload.php");
				url_cmd    = (server + "/command.php").Replace("//command.php","/command.php");			
				
				timer.Interval = (int)nud_delay.Value;
				timer.Start();
				btn_start.Text = "&Stop";
			}else{
				timer.Stop();
				btn_start.Text = "&Start";
			}
		}
		
		void Btn_hideClick(object sender, EventArgs e)
		{
			showForm = false;
			this.Hide();
		}
		
		void Nud_delayLeave(object sender, EventArgs e)
		{
			saveConfig();
		}
		
		void MainFormFormClosing(object sender, FormClosingEventArgs e)
		{
			//saveConfig();
		}
		
		
		
		void LogMouseClick(object sender, MouseEventArgs e)
		{
			tempcounter = -3;
		}
		
		void Timer_syncScreenTick(object sender, EventArgs e)
		{	
//			timer_syncScreen.Stop();
//			if( File.Exists(file_last) ){
//				Bitmap lastImg = (Bitmap)Image.FromFile(file_last);
//				if( ComparingImage.Compare( ImageBitmap, lastImg ) == ComparingImage.CompareResult.ciCompareOk ){
//					timer_syncScreen.Start();
//					return;
//				}
//			}
			executeUploadScreen();
			//timer_syncScreen.Start();
		}
		
		void Cbx_autoUploadScreenCheckedChanged(object sender, EventArgs e)
		{
			if( cbx_syncScreen.Checked ){
				timer_syncScreen.Interval = ((int)nud_syncScreen.Value) * 1000;
				timer_syncScreen.Start();
			}else{
				timer_syncScreen.Stop();
			}
		}
	}
}
